﻿using csharp_networkprotocol_hpsocket;
using HPSocket;
using HPSocket.Base;
using HPSocket.Sdk;
using System;
using System.Data;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Text;
using System.Windows.Forms;

namespace HPSocket_Client
{
    public partial class TCPClientOld : Form
    {
        /// <summary>
        ///  HPSocket_TCPServer示例帮助类（示例学习）
        /// </summary>
        HPSocket_TcpClientHelper _HPSocket_TcpClientHelper = new HPSocket_TcpClientHelper();

        /// <summary>
        /// 包数据结束符
        /// </summary>
        private readonly string _endsWith = "\r\n";

        public TCPClientOld()
        {
            InitializeComponent();
        }

        private void TCPClientOld_Load(object sender, EventArgs e)
        {

        }

        /// <summary>
        /// 连接
        /// </summary>
        private async void button1_Click(object sender, EventArgs e)
        {
            try
            {
                if (button1.Text == "连接")  // 开启监听
                {
                    // 检查地址
                    if (!CheckServerUrl())
                    {
                        return;
                    }

                    string address = txtIPAddress.Text.Trim();        // IP
                    ushort port = ushort.Parse(txtPort.Text.Trim());  // 端口

                    // <2>配置TCPServer的参数
                    _HPSocket_TcpClientHelper.Address = address;        // IP
                    _HPSocket_TcpClientHelper.Port = port;              // 端口
                    _HPSocket_TcpClientHelper.SocketBufferSize = 4096;  // 缓存4K
                    if (checkBox1.Checked)
                    {
                        _HPSocket_TcpClientHelper.BindAddress = txtIP2.Text.Trim();  // 本地绑定到哪个ip
                        _HPSocket_TcpClientHelper.BindPort = (ushort)Convert.ToInt32(txtPort2.Text.Trim());   // 本地绑定到哪个端口
                    }

                    // <3> 绑定事件
                    //event ClientPrepareConnectEventHandler OnPrepareConnect;  // 准备连接了事件
                    //event ClientConnectEventHandler OnConnect;      // 连接事件
                    //event ClientHandShakeEventHandler OnHandShake;  // TCP握手成功事件
                    //event ClientSendEventHandler OnSend;            // 数据包发送事件
                    //event ClientReceiveEventHandler OnReceive;      // 数据包到达事件
                    //event ClientCloseEventHandler OnClose;          // TCP连接关闭事件
                    _HPSocket_TcpClientHelper._client.OnPrepareConnect += OnPrepareConnect;  // 准备连接了事件
                    _HPSocket_TcpClientHelper._client.OnConnect += OnConnect;                // 连接事件
                    _HPSocket_TcpClientHelper._client.OnHandShake += OnHandShake;            // TCP握手成功事件
                    _HPSocket_TcpClientHelper._client.OnSend += OnSend;                      // 数据包发送事件
                    _HPSocket_TcpClientHelper._client.OnReceive += OnReceive;                // 数据包到达事件
                    _HPSocket_TcpClientHelper._client.OnClose += OnClose;                    // TCP连接关闭事件

                    bool connResult = _HPSocket_TcpClientHelper.Connect();  // 连接
                    if (connResult)
                    {
                        Showbutton1(true, "断开");
                    }
                    else
                    {
                        Showbutton1(false, "连接");
                    }
                }
                else  // 关闭监听
                {
                    _HPSocket_TcpClientHelper.Stop();
                    _HPSocket_TcpClientHelper._client.OnPrepareConnect -= OnPrepareConnect;  // 准备连接了事件
                    _HPSocket_TcpClientHelper._client.OnConnect -= OnConnect;                // 连接事件
                    _HPSocket_TcpClientHelper._client.OnHandShake -= OnHandShake;            // TCP握手成功事件
                    _HPSocket_TcpClientHelper._client.OnSend -= OnSend;                      // 数据包发送事件
                    _HPSocket_TcpClientHelper._client.OnReceive -= OnReceive;                // 数据包到达事件
                    _HPSocket_TcpClientHelper._client.OnClose -= OnClose;                    // TCP连接关闭事件

                    Showbutton1(false, "连接");
                }
            }
            catch (Exception ex)
            {
                ShowLog($"连接/关闭TCP客户端 {txtIPAddress.Text}:{txtPort.Text} 失败，错误信息：" + ex.Message);
            }
        }

        /// <summary>
        /// 发送
        /// </summary>
        private async void btnSendMsg_Click(object sender, EventArgs e)
        {
            try
            {
                // 检查地址
                if (!_HPSocket_TcpClientHelper._client.IsConnected || _HPSocket_TcpClientHelper._client.State != ServiceState.Started)
                {
                    ShowLog("TCP客户端未连接到任何TCP服务器！");
                    return;
                }
                string sendMsg = txtMsg.Text;  // 
                if (string.IsNullOrEmpty(sendMsg))
                {
                    ShowLog("发送信息不可为空！");
                    return;
                }
                byte[] bytes = Encoding.UTF8.GetBytes(sendMsg);
                int length = bytes.Length;

                bool resultData_TCP = _HPSocket_TcpClientHelper.Send(bytes, length);  // 发送
                // 显示信息-略
            }
            catch (Exception ex)
            {
                ShowLog("发送信息错误，错误信息：" + ex.Message);
            }
        }

        #region 事件
        /// <summary>
        /// 准备连接了事件
        /// </summary>
        /// <param name="sender">客户端</param>
        /// <param name="socket">客户端Id</param>
        /// <returns></returns>
        private HandleResult OnPrepareConnect(IClient sender, IntPtr socket)
        {
            sender.ExtraData = string.Empty;  // 设置附加数据（用来做粘包处理）

            return HandleResult.Ok;
        }
        /// <summary>
        /// 连接事件
        /// </summary>
        /// <param name="sender">客户端</param>
        /// <returns></returns>
        private HandleResult OnConnect(IClient sender)
        {
            ShowLog(string.Format("TCP客户端([{0}]{1}:{2})接入TCP服务器{3}:{4}", sender.ConnectionId, sender.BindAddress, sender.BindPort, sender.Address, sender.Port));
            return HandleResult.Ok;
        }
        /// <summary>
        /// TCP握手成功事件
        /// </summary>
        /// <param name="sender">客户端</param>
        /// <returns></returns>
        private HandleResult OnHandShake(IClient sender)
        {
            // 一般用不到
            return HandleResult.Ok;
        }
        /// <summary>
        /// 数据包发送事件
        /// </summary>
        /// <param name="sender">客户端</param>
        /// <param name="data">数据</param>
        /// <returns></returns>
        private HandleResult OnSend(IClient sender, byte[] data)
        {
            ShowLog(string.Format("TCP客户端发送数据到TCP服务器[{0}]{1}:{2};数据内容[长度{3}]：{4}", sender.ConnectionId, sender.Address, sender.Port, data.Length, Encoding.UTF8.GetString(data)));
            return HandleResult.Ok;
        }
        /// <summary>
        /// 数据包到达事件
        /// </summary>
        /// <param name="sender">客户端</param>
        /// <param name="data">数据</param>
        /// <returns></returns>
        private HandleResult OnReceive(IClient sender, byte[] data)
        {
            // <1> 获取附加数据对象
            if (!(sender.ExtraData is string extraDataStr))
            {
                return HandleResult.Error;
            }

            // <2> 将接收数据转换成字符串
            string msg = Encoding.UTF8.GetString(data);
            extraDataStr += msg;  // 添加数据到缓存_不合格的数据添加到缓存区（用于粘包、拆包）

            // <3> 显示信息
            ShowLog(string.Format("TCP客户端接收到TCP服务器[ID:{0},IP:‘{1}:{2}’]的信息;数据:[长度{3}]: {4}", sender.ConnectionId, sender.Address, sender.Port, data.Length, msg));

            // <4> 处理数据
            HandleResult result;
            while (true)
            {
                int index = extraDataStr.IndexOf(_endsWith);
                if (index == -1) // 数据接收不完整，忽略后等待下一次接收
                {
                    result = HandleResult.Ignore;
                    break;
                }
                else
                {
                    string validMsg = extraDataStr.Remove(0, index);
                    // <6> 业务处理-异步(validMsg内容解析时的格式校验属于业务范畴)

                    // <7> 移除已取出数据
                    extraDataStr = extraDataStr.Remove(0, index + _endsWith.Length);
                }
            }

            // <5> 保存PacketData数据
            if (extraDataStr.Length > _HPSocket_TcpClientHelper.SocketBufferSize)  // 可选-控制长度为4096(注：实际所占空间大小>4096)
            {
                int length_Delete = extraDataStr.Length - Convert.ToInt32(_HPSocket_TcpClientHelper.SocketBufferSize);
                extraDataStr = extraDataStr.Remove(0, length_Delete);  // 清除长度超标数据
            }
            sender.ExtraData = extraDataStr;  // 初始化附加信息

            return result;
        }
        /// <summary>
        /// TCP连接关闭事件
        /// </summary>
        /// <param name="sender">客户端</param>
        /// <param name="socketOperation">关闭类型</param>
        /// <param name="errorCode">错误代码</param>
        /// <returns></returns>
        private HandleResult OnClose(IClient sender, SocketOperation socketOperation, int errorCode)
        {
            sender.ExtraData = null;  // 删除附加数据
            ShowLog(string.Format("TCP客户端断开与TCP服务器[{0}] {1}:{2}的连接, 断开类型: {3},错误代码: {4}", sender.ConnectionId, sender.Address, sender.Port, socketOperation.ToString(), errorCode));
            return HandleResult.Ok;
        }
        #endregion 事件

        #region 方法
        /// <summary>
        /// 开关按钮刷新
        /// </summary>
        /// <param name="msg">信息</param>
        public void Showbutton1(bool isSuccess, string text)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action<bool, string>(Showbutton1), isSuccess, text);
                return;
            }

            button1.BackColor = isSuccess ? Color.FromArgb(128, 255, 128) : Color.FromArgb(255, 128, 128);
            button1.Text = text;  // isSuccess? "关闭监听-控制线程" : "开启监听-控制线程";
        }

        /// <summary>
        /// 显示信息
        /// </summary>
        /// <param name="msg">信息</param>
        public void ShowLog(string msg)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action<string>(ShowLog), msg);
                return;
            }
            if (rtxtInfo.Text.Length > 2000)
            {
                rtxtInfo.Text = string.Empty;
            }
            rtxtInfo.AppendText(string.Concat("\r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), "->", msg));
        }

        /// <summary>
        /// 检查连接是否正常
        /// </summary>
        /// <returns>true为通过</returns>
        private bool CheckServerUrl()
        {

            if (string.IsNullOrEmpty(txtIPAddress.Text))  // 
            {
                ShowLog("发送信息不可为空！");
                return false;
            }
            if (string.IsNullOrEmpty(txtPort.Text))  // 
            {
                ShowLog("端口不可为空！");
                return false;
            }
            return true;
        }
        #endregion 方法
    }
}
